<script setup lang="ts">
import { reactive, toRefs, computed, ref, watch, h, VNode } from 'vue';
import { Icon } from '@iconify/vue';
import { ItemType, resultOptions, useTable } from '@/components/core/dynamic-table/helper';
import DynamicTable, { TableColumn, TableController } from '@/components/core/dynamic-table';
import { Columns, SpanMethodProps, submitFormItems, SummaryMethodProps } from './table-data';
import { ElMessageBox, ElPagination, ElSwitch, ElSelect, ElOption } from 'element-plus';
import { ElDatePicker } from 'element-plus';
import { modelFormItemsProps, SchemaForm, useQueryForm } from '@/components/core/schema-form';
import { formItems } from './table-data';
import { message } from '@/components/basic/message';
import OrderDetail, { OrderDetailExpose } from './component/OrderDetail';
import { type IObject } from '@/components/core/dynamic-table/helper';
import { SchemaOptions, SchemaResultOptions } from '@/components/core/schema-form';
import { ADialogInstance } from '@/components/basic/dialog';
import { DefaultService as Api } from '@/servers';
import { ContextMenuExpose, MouseMenu } from '@/components/business/context-menu';
import { debounce } from '@/utils/debounce';
import { ProductItem } from './component/ProductItem';
import { ChooseProduct } from '@/components/business/product';

const schema = reactive({
  formItems: formItems,
  data: {},
  url: 'getOrderSelect',
  queryParams: [
    ['webType', 'data.list:0', 'content'],
    ['itemType', 'data.list:1', 'content'],
    ['categoryId', 'data', 'categories', '分类'],
    ['countryId', 'data', 'countries', '国家'],
    ['status', 'data.list:3', 'content'],
    ['shipway', 'data.list:2', 'content']
  ]
}) as unknown as SchemaOptions;

const optionState = reactive({ ...useQueryForm(schema), ...toRefs(schema) }) as SchemaResultOptions;

const editDialogRef = ref<ADialogInstance>();
const base = reactive({
  query: 'getOrderList',
  delete: 'postOrderDelete',
  data: [],
  multiple: [],
  Params: [
    'page',
    'size',
    'qForm.sort',
    'qForm.webType',
    'qForm.categoryId',
    'qForm.itemType',
    'qForm.shipway',
    'qForm.countryId',
    'qForm.status',
    'qForm.orderno',
    'qForm.code',
    'qForm.dash',
    'qForm.username'
  ],
  listUrl: 'data.list',
  sort: (a: ItemType, b: ItemType): number => a.id - b.id,
  page: 1,
  size: 14,
  total: 0,
  qForm: {
    sort: 0,
    webType: '',
    categoryId: '',
    itemType: '',
    status: [],
    countryId: [],
    orderno: '',
    shipway: '',
    code: '',
    dash: '',
    username: '',
    formData: ''
  },
  form: {
    id: '',
    mid: '',
    webType: '',
    // orderno: '',
    // subamount: '',
    // total_nums: '',
    addressId: '',
    // status: '',
    ship_at: '',
    payway: '',
    shipway: '',
    shipping: '',
    // chargeWeight: '',
    items: [{ itemid: '', nums: 1, price: 0 }] // { itemid: '', nums: '', price: '' }
  },
  openEdit: () => editDialogRef.value?.openModel()
});

const tableState = reactive({ ...useTable(base), ...toRefs(base) }) as resultOptions;

const mouseMenu = [
  {
    icon: 'ep:edit-pen',
    label: '编辑',
    id: 'edit'
  },
  {
    icon: 'ep:delete',
    label: '删除',
    id: 'delete'
  }
];

const mouseMenuRef = ref<ContextMenuExpose>();
const emitMouseMenu = (row: IObject, col: IObject, e: Event) => {
  if (row || col) {
    mouseMenuRef.value?.emitContextMenu(e);
  }
};

const queryUsernameOptionsLoading = ref(false);
const submitFormItemsState = ref(submitFormItems);
const queryUserNameOptions = debounce(async (query: string) => {
  if (!query) return;
  queryUsernameOptionsLoading.value = true;
  const res = await Api.getOrderMembers(tableState.form.webType, query);
  queryUsernameOptionsLoading.value = false;
  const list = res.data.list;
  if (list.length) {
    const target = submitFormItemsState.value.find(i => i.prop === 'mid')!;
    target.options = list.map(i => ({ label: i.username, value: i.id }));
  }
}, 1000);
const changeUserName = async (mid: number) => {
  const res = await Api.getOrderAddress(mid);
  const list = res.data.list;
  if (list.length) {
    const target = submitFormItemsState.value.find(i => i.prop === 'addressId')!;
    target.options = list.map(i => ({
      label:
        (i.fName || '') +
        ' ' +
        (i.lName || '') +
        ',' +
        (i.aDetail || '') +
        ',' +
        (i.aCity || '') +
        ',' +
        (i.aCountry || '') +
        ',' +
        (i.postcode || ''),
      value: i.id
    }));
  }
};

const submit = (item: ItemType) => {
  console.log(item);
};

const tableDataList = computed(() => {
  return tableState.data || [];
});

// const list = ref<IObject[]>([]);
const originData = ref<IObject[]>([]);
const list = computed(() => {
  if (!withor.value) return originData.value;
  const { code, dash } = tableState.qForm;
  return originData.value.filter(
    i => i.code && code && i.dash && dash && i.code.includes(code) && i.dash.includes(dash)
  );
});

const withor = ref(false); // &: true |: false
watch(
  tableDataList,
  (newList: IObject[]) => {
    originData.value = newList
      .reduce((pre, cur) => {
        const { order_items, ...rest } = cur;
        if (order_items.length) {
          order_items.forEach((item: IObject) => {
            pre.push({
              rowKey: `${rest.id}-${item.itemid}-${Math.random().toString(36).substring(2, 9)}`,
              ...rest,
              ...item
            });
          });
        }

        return pre;
      }, [])
      .sort((a: IObject, b: IObject) => a.id - b.id);
  },
  { immediate: true }
);

const arraySpanMethod = ({ row, column, rowIndex, columnIndex }: SpanMethodProps) => {
  String(column);
  if (columnIndex < 4 || columnIndex > 9) {
    if (rowIndex > 0 && row.orderno === list.value[rowIndex - 1].orderno) return { rowspan: 0, colspan: 0 };

    const rowspan = list.value.filter((i: IObject) => i.orderno === row.orderno).length;

    return { rowspan, colspan: 1 };
  }
};

const TotalProps = ['nums', 'carton', 'amount'];
const getSummaries = (param: SummaryMethodProps) => {
  const { columns, data } = param;

  const sums: (string | VNode)[] = [];
  columns.forEach((column, index) => {
    if (index === 0) {
      sums[index] = h('div', ['Total']);
      return;
    }

    if (TotalProps.includes(column.property)) {
      const values = data.map(item => Number(item[column.property]));
      sums[index] =
        '' +
        values
          .reduce((prev, curr) => {
            const value = Number(curr);
            if (!Number.isNaN(value)) {
              return prev + curr;
            } else {
              return prev;
            }
          }, 0)
          .toFixed(column.property === 'amount' ? 2 : 0);
    } else {
      sums[index] = ' ';
    }
  });
  return sums;
};

const orderDetailRef = ref<OrderDetailExpose>();
const openDrawer = async (item: IObject) => {
  orderDetailRef.value?.closeDrawer();
  message.loading();
  await orderDetailRef.value?.init(item);
  setTimeout(() => {
    message.destroy();
  }, 200);
};

const batchDialogRef = ref<ADialogInstance>();
const batchForm = ref<{
  id: string[];
  status: number;
}>({
  id: [],
  status: 0
});

const openBatchDialog = (operate: string) => {
  if (!tableState.multiple?.length) return message.error('请选择订单');

  batchForm.value.id = tableState.multiple!.map(i => i.id);
  if (operate === 'batch') {
    return batchDialogRef.value?.openModel();
  } else {
    ElMessageBox.confirm('确定要拆分吗？', '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })
      .then(confirm => {
        if (!confirm) return;
        if (operate === 'split') Api.postOrderSplit({ 'ids[]': batchForm.value.id });
        if (operate === 'merge') Api.postOrderMerge({ 'ids[]': batchForm.value.id });
      })
      .then(() => tableState.fetchData())
      .catch(() => {
        message.error('取消操作');
      });
  }
};

const batchSubmit = async () => {
  const { id, status } = batchForm.value;
  await Api.postOrderModify(id, status);
  tableState.fetchData();
};

const addItem = () => {
  tableState.form.items.push({ itemid: '', nums: 1, price: 0 });
};
const deleteItem = (index: number) => {
  tableState.form.items.splice(index, 1);
};
const chooseProductRef = ref();
const showProductDialog = (index: number) => {
  chooseProductRef.value?.openModel(index);
};
</script>
<template>
  <div class="wh-full flex flex-col box-border pb-2" v-loading="optionState.loading && tableState.loading">
    <TableController background="transparent">
      <template #left>
        <SchemaForm
          v-if="!optionState.loading"
          :formItems="optionState.formItems as any"
          :model="tableState.qForm"
          label-position="left"
          inline
          clearFormItem
          @reload-table-data="tableState.fetchData"
        >
          <template #footer>
            <a-button type="primary" @click="tableState.fetchData()">Search</a-button>
          </template>
        </SchemaForm>
      </template>
    </TableController>
    <TableController>
      <template #left>
        <a-button @click="openBatchDialog('batch')" type="primary">batch</a-button>
        <a-button @click="openBatchDialog('split')" plain type="danger">split</a-button>
        <a-button @click="openBatchDialog('merge')" plain type="primary">merge</a-button>
        <a-button @click="openBatchDialog('notify')" plain type="warning">notify</a-button>
      </template>
      <template #right>
        <ElSwitch v-model="withor" />
        <a-button type="success">Export</a-button>
        <a-button type="primary" @click="tableState.editRowItem!()">Add</a-button>
        <!-- <a-button type="danger">Delete</a-button> -->
      </template>
    </TableController>
    <div class="overflow-y-auto w-full p-1 box-border" style="background-color: var(--el-bg-color)">
      <DynamicTable
        border
        show-summary
        height="100%"
        :columns="Columns as unknown as TableColumn<any>[]"
        :default-expand-all="false"
        row-key="rowKey"
        :data="list"
        show-overflow-tooltip
        v-loading="!optionState.loading && tableState.loading"
        header-row-class-name="table-header"
        :span-method="arraySpanMethod"
        :summary-method="getSummaries"
        @selection-change="tableState.selectionChange"
        @row-contextmenu="emitMouseMenu"
      >
        <!-- <ElTableColumn type="selection" width="55" /> -->
        <template #date="container">
          {{ String(container.scope.row.created_at).substring(0, 5) || '-' }}
        </template>
        <template #code="container">
          {{ container.scope.row[container.scope.column.property] || '-' }}
        </template>
        <template #orderno="container">
          <span class="color-blue cursor-pointer" @click="openDrawer(container.scope.row)">{{
            container.scope.row.orderno || '-'
          }}</span>
        </template>
        <template #username="container">
          <span>{{ container.scope.row.username }}</span>
          <br />
          <span>{{ container.scope.row.realname }}</span>
        </template>
        <template #price="container">
          <div class="flex-cc">
            <Icon icon="ant-design:dollar-circle-outlined" color="#f00" />
            <div>
              {{ container.scope.row.price || '-' }}
            </div>
          </div>
        </template>
        <template #amount="container">
          <div class="flex-cc">
            <Icon icon="ant-design:dollar-circle-outlined" color="#f00" />
            <div>
              {{ Number(container.scope.row.amount).toFixed(2) || '-' }}
            </div>
          </div>
        </template>
        <template #operate="container">
          <a-button type="info" size="small" @click="tableState.editRowItem!(container.scope.row)">
            <!-- 编辑 -->
            <Icon icon="ant-design:edit-outlined" />
          </a-button>
          <a-button type="danger" size="small" @click="tableState.deleteRowItem!(container.scope.row)">
            <!-- 删除 -->
            <Icon icon="ant-design:delete-outlined" />
          </a-button>
        </template>
      </DynamicTable>
    </div>
    <TableController>
      <template #right>
        <el-pagination
          background
          layout="prev, pager, next"
          :page-size="tableState.size"
          :total="tableState.total"
          v-model:current-page="tableState.page"
          @change="tableState.pageCurrentChangeHandle"
        />
      </template>
    </TableController>
    <a-dialog ref="batchDialogRef" title="Batch Edit" width="400" @confirm="batchSubmit" draggable>
      <SchemaForm
        :formItems="[
          {
            label: '订单状态',
            type: 'select',
            prop: 'status',
            options: formItems.find(item => item.prop === 'status')?.options || []
          }
        ]"
        :model="batchForm"
        label-position="left"
        clearFormItem
      >
      </SchemaForm>
    </a-dialog>
    <OrderDetail ref="orderDetailRef" />
    <MouseMenu ref="mouseMenuRef" domId="---" :list="mouseMenu" />
    <a-dialog ref="editDialogRef" title="Edit" width="1100" @confirm="tableState.fetchData" draggable>
      <div class="w-full flex flex-row gap-2">
        <SchemaForm
          class="w-450px"
          v-if="!optionState.loading"
          :formItems="submitFormItemsState as any"
          :model="tableState.form"
          label-width="80px"
          label-position="left"
          clearFormItem
          @reload-table-data="tableState.fetchData"
        >
          <template #webType>
            <ElSelect v-model="tableState.form.webType" class="min-w-192px" placeholder="请选择" clearable>
              <ElOption
                v-for="(item, index) in optionState.formItems.find(item => item.prop === 'webType')!.options"
                :key="index"
                :label="item.label"
                :value="item.value"
              />
            </ElSelect>
          </template>
          <template #address>
            <ElSelect v-model="tableState.form.addressId" class="min-w-192px" placeholder="请选择" clearable>
              <ElOption
                v-for="(item, index) in (submitFormItemsState as modelFormItemsProps[]).find(
                  item => item.prop === 'addressId'
                )!.options"
                :key="index"
                :label="item.label"
                :value="item.value"
              />
            </ElSelect>
          </template>
          <template #shipway>
            <ElSelect v-model="tableState.form.webType" class="min-w-192px" placeholder="请选择" clearable>
              <ElOption
                v-for="(item, index) in optionState.formItems.find(item => item.prop === 'webType')!.options"
                :key="index"
                :label="item.label"
                :value="item.value"
              />
            </ElSelect>
          </template>
          <template #mid>
            <ElSelect
              v-model="tableState.form.mid"
              placeholder="请选择"
              style="min-width: 192px"
              :loading="queryUsernameOptionsLoading"
              filterable
              remote
              @change="changeUserName"
              :remote-method="queryUserNameOptions"
              clearable
            >
              <ElOption
                v-for="(item, index) in (submitFormItemsState as modelFormItemsProps[]).find(
                  item => item.prop === 'mid'
                )!.options"
                :key="index"
                :label="item.label"
                :value="item.value"
              />
            </ElSelect>
          </template>
          <template #date>
            <ElDatePicker
              v-model="tableState.form.ship_at"
              type="date"
              placeholder="请选择日期"
              value-format="YYYY-MM-DD"
              style="width: 100%"
            />
          </template>
          <template #payType> </template>
        </SchemaForm>
        <div class="flex-1">
          <TransitionGroup name="list" tag="ul">
            <!-- 
              表单盒子
                1. 第一行商品名称，右边按钮，点击弹出商品选择框
                2. 第二行商品单价 订购个数 小计金额
            -->
            <li
              v-for="(item, index) in tableState.form.items"
              :key="item"
              class="flex flex-col border border-solid border-gray-200 rounded-lg mb-4"
            >
              <ProductItem
                :item="item"
                :index="index"
                @deleteItem="deleteItem(index)"
                @showProductDialog="showProductDialog"
              />
            </li>
          </TransitionGroup>
          <!-- 虚线边 淡蓝色按钮 加号 -->
          <div
            class="w-full border min-h-30px cursor-pointer border-dashed border-blue-300 rounded-lg flex justify-center items-center"
            @click="addItem"
          >
            <Icon icon="ep:plus" class="text-2xl text-blue-300" />
          </div>
        </div>
      </div>
    </a-dialog>
    <ChooseProduct ref="chooseProductRef" @chooseProduct="chooseProduct" />
  </div>
</template>
<style lang="scss" scoped>
.list-enter-active,
.list-leave-active {
  transition: all 0.5s ease;
}
.list-enter-from,
.list-leave-to {
  opacity: 0;
  transform: translateX(30px);
}
</style>
